#include "TestHashing.h"

#include "includes.h"
#include "../src/indices/IndiceHash.h"
#include "../src/recursoDeAlmacenamiento/RecursoDeAlmacenamientoIndexado.h"
#include "../src/recursoDeAlmacenamiento/FabricaRecursosAlmacenamiento.h"
#include "../src/indices/hash/Hash.h"

TestHashing::TestHashing() {

}

TestHashing::~TestHashing() {

}

void TestHashing::run() {
	this->testSinSplit();
	this->testSplit();
	this->testCompleto();
	this->testSuperDuper();
}

void TestHashing::testSinSplit() {

	string path = "./Archivos/hash/simple";
	system("rm -r -f ./Archivos/hash_simple*");

	int tamanioDato = 5;

	/* Se setea un tamanio de bucket grande para que no haya split */
	this->recurso
	= FabricaRecursosAlmacenamiento::getFabrica()->crearRecursoIndexadoRegistros(path, tamanioDato,
			new IndiceHash(path,new TipoClaveChar(), 1000),DIFERIDA);


	Bytes dato1("chaja");
	Bytes dato2("adria");
	Bytes dato3("gonza");
	Bytes dato4("spine");
	Bytes dato5("rodri");

	recurso->guardar(dato1);
	recurso->guardar(dato2);
	recurso->guardar(dato3);
	recurso->guardar(dato4);
	recurso->guardar(dato5);

	Key clave(new ClaveString("s"));
	assert(recurso->cargar(clave).toString() == dato4.toString(), "Test: Indice Hash clave 's'");

	Key clave2(new ClaveString("a"));
	assert(recurso->cargar(clave2).toString() == dato2.toString(), "Test: Indice Hash clave 'a'");

	Key clave3(new ClaveString("r"));
	assert(recurso->cargar(clave3).toString() == dato5.toString(), "Test: Indice Hash clave 'r'");

	assert(!recurso->guardar(dato3),"Test: No acepta copias");
	delete this->recurso;
}

void TestHashing::testSplit() {

	string path = "./Archivos/hash/split";

	system("rm -r -f ./Archivos/hash/split*");
	int tamanioDato = 5;

	/* Se setea un tamanio de bucket pequenio para que haya split */
	this->recurso
	= FabricaRecursosAlmacenamiento::getFabrica()->crearRecursoIndexadoRegistros(path, tamanioDato,
			new IndiceHash(path,new TipoClaveChar(), 25), DIFERIDA);


	Bytes dato1("chaja");
	Bytes dato2("adria");
	Bytes dato3("gonza");
	Bytes dato4("spine");
	Bytes dato5("rodri");
	Bytes dato6("danyk");

	recurso->guardar(dato1);
	recurso->guardar(dato2);
	recurso->guardar(dato3);
	recurso->guardar(dato4);
	recurso->guardar(dato5);
	recurso->guardar(dato6);

	Key clave(new ClaveString("s"));
	assert(recurso->cargar(clave).toString() == dato4.toString(), "Test Split: Indice Hash clave 's'");

	Key clave2(new ClaveString("g"));
	assert(recurso->cargar(clave2).toString() == dato3.toString(), "Test Split: Indice Hash clave 'a'");

	Key clave3(new ClaveString("r"));
	assert(recurso->cargar(clave3).toString() == dato5.toString(), "Test Split: Indice Hash clave 'r'");

	delete this->recurso;
}

void TestHashing::testCompleto() {

	cout << "Test completo" << endl << endl;

	string path = "./Archivos/hash/completo";
	system("rm -r -f ./Archivos/hash_completo*");

	int tamanioDato = 5;

	/* Se setea un tamanio de bucket pequenio para que haya split */
	this->recurso
	= FabricaRecursosAlmacenamiento::getFabrica()->crearRecursoIndexadoRegistros(path, tamanioDato,
			new IndiceHash(path,new TipoClaveChar(), 25), DIFERIDA);

	TipoClaveChar extractor;

	Bytes dato1("chaja");
	Bytes dato2("adria");
	Bytes dato3("gonza");
	Bytes dato4("spine");
	Bytes dato5("rodri");

	recurso->guardar(dato1);
	recurso->guardar(dato2);
	recurso->guardar(dato3);
	recurso->guardar(dato4);
	recurso->guardar(dato5);

	Key clave5 = extractor.crearClave(extractor.extraerClave(dato5));
	recurso->eliminar(clave5);

	Key clave4 = extractor.crearClave(extractor.extraerClave(dato4));
	recurso->eliminar(clave4);

	Key clave3 = extractor.crearClave(extractor.extraerClave(dato3));
	recurso->eliminar(clave3);

	assert(recurso->cargar(clave4).toString() == "", "Test Completo: Indice Hash clave 's'");

	assert(recurso->cargar(clave3).toString() == "", "Test Completo: Indice Hash clave 'a'");

	Key clave1(new ClaveString("c"));
	assert(recurso->cargar(clave1).toString() == dato1.toString(), "Test Completo: Indice Hash clave 'c'");

	delete this->recurso;
}

void TestHashing::testSuperDuper() {

	cout << "Test super duper" << endl << endl;

	string path = "./Archivos/hash/super";

	system("rm -r -f ./Archivos/hash/super*");
	int tamanioDato = 20;

	this->recurso
	= FabricaRecursosAlmacenamiento::getFabrica()->crearRecursoIndexadoBloques(path, tamanioDato,
			new IndiceHash(path,new TipoClaveChar(), 30), DIFERIDA);

	Bytes dato1("martin");
	Bytes dato2("chaco");
	Bytes dato3("spinelli");
	Bytes dato4("dany");
	Bytes dato5("rodrix");
	Bytes dato6("valenkpo");
	Bytes dato7("horsy");
	Bytes dato8("lele");
	Bytes dato9("byzarro");
	Bytes dato10("ybuenoo");

	recurso->guardar(dato1);
	recurso->guardar(dato2);
	recurso->guardar(dato3);
	recurso->guardar(dato4);
	recurso->guardar(dato5);
	recurso->guardar(dato6);
	recurso->guardar(dato7);
	recurso->guardar(dato8);
	recurso->guardar(dato9);
	recurso->guardar(dato10);

	Key claveLele(new ClaveString("l"));

	Bytes dato11("lela");
	recurso->modificar(dato11);

	assert(recurso->cargar(claveLele).toString() == "lela", "Test Obtener");

	Key claveRodrix(new ClaveString("r"));
	recurso->eliminar(claveRodrix);

	Key claveBizarra(new ClaveString("b"));
	recurso->eliminar(claveBizarra);

	assert(!recurso->eliminar(claveBizarra), "Probando eliminar clave eliminada");
	assert(recurso->cargar(claveRodrix).toString() == "", "Probando cargar clave eliminada");

	delete this->recurso;
}
